package circle

type Circle struct {
	rp   uint32
	wp   uint32
	num  uint32
	mask uint32
	data []interface{}
}

func New(num uint32) *Circle {
	c := new(Circle)
	c.num = (uint32)(1) << num
	c.mask = c.num - 1
	c.data = make([]interface{}, c.num)
	return c
}

func (c *Circle) Pop() (i interface{}) {
	if c.rp == c.wp {
		return nil
	}

	i = c.data[c.rp&c.mask]
	c.rp++
	return i
}

func (c *Circle) Push(i interface{}) bool {
	if c.wp-c.rp >= c.num {
		return false
	}

	c.data[c.wp&c.mask] = i
	c.wp++
	return true
}

func (c *Circle) Size() uint32 {
	return c.wp - c.rp
}

func (c *Circle) Reset() {
	c.rp = 0
	c.wp = 0
}

func (c *Circle) Capacity() uint32 {
	return c.num
}
